#include <thread>
#include <sys/time.h>
#include <stdio.h>
#include "UsbAVStream.h"
#include "UsbStreamTest.h"
#include "log.h"

using namespace Usbstream;

unsigned long currentMillionSeconds() {
    struct timeval tp{};
    gettimeofday(&tp, nullptr);

    unsigned long now = tp.tv_sec * 1000 + tp.tv_usec / 1000;
    return now;
}
unsigned long lastPacketTime = -1;
unsigned long packetNums = 0;
unsigned long allPacketTimes = 0;
unsigned long allPacketNums = 0;


void UsbStreamTest::UvcIn(string usbport){
	//lam用于设备热插拔中出现的段错误和重新插入拉流问题
	//在获取设备对象拉流之前先设置回调
#if 0
	auto lam1 = [usb_stream, usbport](string usbport_key, bool status){
		if(usbport != usbport_key){
			return ;
		}
		if(!status){
			//如果是断开连接的话就需要将当前调用的对象置空，以后的每次调用先判断这个值是不是为空
		}else{
			//重新设置流的参数重新拉流
			//判断如果不具备当前的能力就睡一会儿,直到准备好对象，这里需要注意设备一定需要具备这个能力，不然会导致最终调用接口失败
			//再次判断
			//重新获取能力对象重新拉流，需要重新从map中获取设备对象，重新调用getsupportParams，setParams，startStream
		}
	};
#endif
	Json::Value params;
	UsbAVStream::instance() -> getSupportParams("usb-1.1" , UVCIN, params);
	LOG_PrintInfo("UVCIN:%d ---> %s", UVCIN,  params.toStyledString().c_str());
	Json::Value paramsset = params["Formats"][0];
	LOG_PrintInfo("UVCINset:%d ---> %s", UVCIN,  paramsset.toStyledString().c_str());
	UsbAVStream::instance() -> setParams("usb-1.1", UVCIN, paramsset);

	auto lam = [usbport](void *addr, int length)
	{

		unsigned long currentTime = currentMillionSeconds();
		if (lastPacketTime != -1 && currentTime - lastPacketTime > 1000){
			allPacketTimes++;

			if (allPacketTimes != 0){
				printf("%s  Average second packetnum: %.1f \n", usbport.c_str(), (float)allPacketNums / allPacketTimes);
			}
			lastPacketTime = currentTime;
			packetNums=0;
		} else if (lastPacketTime == -1){
			lastPacketTime = currentTime;
		}
		packetNums++;
		allPacketNums++;
		return true;
	};
	UsbAVStream::instance() -> startStream("usb-1.1", UVCIN, lam);
	std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 20));
	//确认一下是不是空
	//LOG_PrintInfo("stop stream/n");
	UsbAVStream::instance() -> stopStream("usb-1.1", UVCIN);
	//Json::Value::Members members = params.getMemberNames();
	//for(auto it = members.begin(); it != members.end(); it++){
	//}

}

void UsbStreamTest::UacIn(string usbport){
	char filename[256] = {0};
	//获取对应的拉流总控对象
	Json::Value params;
	UsbAVStream::instance() -> getSupportParams("usb-1.1" , UACIN, params);
	LOG_PrintInfo("UACIN:%d ---> %s\n", UVCIN,  params.toStyledString().c_str());
	UsbAVStream::instance() -> setParams("usb-1.1" , UACIN, params);

	sprintf(filename, "/nfsroot/xiejm/capture%s.pcm", params["Channels"].asCString());
	FILE *fp = fopen(filename, "wb");
	auto lam = [fp](void * buffer, int length){
		//LOG_PrintInfo("%d ----- %d\n", buffer , length);
		fwrite(buffer, length , 1, fp);
		return true;
	};
	UsbAVStream::instance() -> startStream("usb-1.1", UACIN, lam);
	std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 10));
	UsbAVStream::instance() -> stopStream("usb-1.1", UACIN);
}


void UsbStreamTest::UacOut(string usbport){

	//调用对象的接口使用不同的枚举开启流
	Json::Value params;
	UsbAVStream::instance() -> getSupportParams("usb-1.1" , UACOUT, params);
	LOG_PrintInfo("UACOUT:%d ---> %s\n", UACOUT,  params.toStyledString().c_str());
	UsbAVStream::instance() -> setParams("usb-1.1" , UACOUT, params);
	FILE *fp = NULL;
	int length = 48000 / 1000 * 16;
	//void *buf =  malloc(length * 4);
	void *buf = malloc(length * 4);
	if((fp = fopen("/nfsroot/Linein_48k_1.pcm", "rb")) == NULL)
	{
		printf("打开文件失败 file:%s.\n", "Linein_48k_1.pcm");
	}
	while(fread(buf, 1, length * 4, fp)){
		UsbAVStream::instance() -> writeStream("usb-1.1", UACOUT, buf, length);
		std::this_thread::sleep_for(std::chrono::milliseconds(16));
	}
}

void UsbStreamTest::getUsbAbility(){
	map<string, int> abilitys;
	map<string, int>::iterator it;
	UsbAVStream::instance() -> getAblilityMap(abilitys);
	for(it = abilitys.begin(); it != abilitys.end(); it++){
		LOG_PrintInfo("%s ---> %d\n", it -> first.c_str(), it -> second);

	}
}
